import java.util.*;

class dbProcessor extends Proc {
	public int numberOfRejected;
	public int numberInQueue_job0;
	public int numberInQueue_job1;
	public int numberInQueue_job2;
	public Proc sendTo;
	public int processor_ID;

	Random slump = new Random();

	dbProcessor(Proc sendTo, int id) {
		this.sendTo = sendTo;
		this.processor_ID = id;
		numberInQueue_job0 = 0;
		numberInQueue_job1 = 0;
		numberInQueue_job2 = 0;
		numberOfRejected = 0;
	}

	public void TreatSignal(Signal x) {
		switch (x.signalType) {
		
		// treat signal
		case G.ARRIVAL_JOB_0: {
			numberInQueue_job0++;
			if ((numberInQueue_job1 + numberInQueue_job2 + numberInQueue_job0) == 1) {
				SignalList.SendSignal(G.READY_JOB_0, x.destination, G.time
						+ G.SERVICE_TIME_JOB0);
			}
		}
			break;
		case G.READY_JOB_0: {
			
			numberInQueue_job0--;
			if(overloadAlgorithm() == false){
			  numberOfRejected++;
			  break;
			  }else{
				  SignalList.SendSignal(G.ARRIVAL_JOB_1, x.destination, G.time);
			  }
			
			// Priority.
			if (numberInQueue_job1 > 0) {
				SignalList.SendSignal(G.READY_JOB_1, x.destination, G.time
						+ G.SERVICE_TIME_JOB1);
			} else if (numberInQueue_job2 > 0) {
				SignalList.SendSignal(G.READY_JOB_2, x.destination, G.time
						+ G.SERVICE_TIME_JOB2);
			} else if (numberInQueue_job0 > 0) {
				SignalList.SendSignal(G.READY_JOB_0, x.destination, G.time
						+ G.SERVICE_TIME_JOB0);
			}
		}break;
		case G.ARRIVAL_JOB_1: {

			numberInQueue_job1++;

			if ((numberInQueue_job1 + numberInQueue_job2 + numberInQueue_job0) == 1) {
				SignalList.SendSignal(G.READY_JOB_1, x.destination, G.time
						+ G.SERVICE_TIME_JOB1);
			}
		}
			break;
		case G.READY_JOB_1: {
			numberInQueue_job1--;

			// find the db_processor containing subscriber info.
			// If this db_processor contains the subscriber data (with
			// probability 1/N)
			// then we are done(it does nothing else).
			// if not, it sends a job_2 to the db_processor which contains the
			// subscriber data
			int idDataProcessor = setDestination(); // Random destination with
													// probability = 1/N
			if (idDataProcessor != this.processor_ID) {
				this.sendTo = ArrivalProcessor.dbProcessorNetwork[idDataProcessor];
				SignalList.SendSignal(G.ARRIVAL_JOB_2, sendTo, G.time);
			} else {
				G.numberOfUpdates++;
			}

			// Priority.
			if (numberInQueue_job1 > 0) {
				SignalList.SendSignal(G.READY_JOB_1, x.destination, G.time
						+ G.SERVICE_TIME_JOB1);
			} else if (numberInQueue_job2 > 0) {
				SignalList.SendSignal(G.READY_JOB_2, x.destination, G.time
						+ G.SERVICE_TIME_JOB2);
			} else if (numberInQueue_job0 > 0) {
				SignalList.SendSignal(G.READY_JOB_0, x.destination, G.time
						+ G.SERVICE_TIME_JOB0);
			}
		}
			break;
		case G.ARRIVAL_JOB_2: {
			numberInQueue_job2++;

			if ((numberInQueue_job1 + numberInQueue_job2 + numberInQueue_job0) == 1) {
				SignalList.SendSignal(G.READY_JOB_2, x.destination, G.time
						+ G.SERVICE_TIME_JOB2);
			}
		}
			break;
		case G.READY_JOB_2: {
			numberInQueue_job2--;
			G.numberOfUpdates++;
			// Priority.
			if (numberInQueue_job1 > 0) {
				SignalList.SendSignal(G.READY_JOB_1, x.destination, G.time
						+ G.SERVICE_TIME_JOB1);
			} else if (numberInQueue_job2 > 0) {
				SignalList.SendSignal(G.READY_JOB_2, x.destination, G.time
						+ G.SERVICE_TIME_JOB2);
			} else if (numberInQueue_job0 > 0) {
				SignalList.SendSignal(G.READY_JOB_0, x.destination, G.time
						+ G.SERVICE_TIME_JOB0);
			}
		}
			break;
		}

	}

	// Destination algorithm
	private int setDestination() {
		return slump.nextInt(G.NUMBER_OF_DB_PROCESSORS);
	}

	// Overload control algorithm: true -> accept
	private boolean overloadAlgorithm() {
		switch (G.OVERLOAD_ALGORITHM) {
		case G.TOTAL: {
			return G.LIMIT >= numberInQueue_job1 + numberInQueue_job2;
		}
		case G.WEIGHTED: {
			return G.LIMIT >= G.WEIGHT_1 * numberInQueue_job1 + G.WEIGHT_2
					* numberInQueue_job2;
		}

		}
		// no control;
		return true;
	}

}